package com.lzy.wzy.handle;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.lzy.wzy.mapper.UserMapper;
import com.lzy.wzy.model.UserBean;
import com.lzy.wzy.result.Response;
import com.lzy.wzy.result.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private final static String CLIENT_ID="clientapp";
    private final static String CLIENT_SECRET="$2a$10$yk9Q8HQlZJXAxSFXeaWVe.CgHrE0FoAuava2LfCncecEsW.ioWiOe";
    private final static String GRANT_TYPE="password";
    private ClientDetails clientDetails;
    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private AuthorizationServerTokenServices authorizationServerTokenServices;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ObjectMapper objectMapper;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        log.info("登录成功");
        if (null == clientDetails) {
            log.info("查询 client info");
            clientDetails = clientDetailsService.loadClientByClientId(CLIENT_ID);
            if (null == clientDetails) {
                throw new UnapprovedClientAuthenticationException("clientId不存在" + CLIENT_ID);
            }
        }
        if (!CLIENT_SECRET.equals(clientDetails.getClientSecret())){
            throw new UnapprovedClientAuthenticationException("clientSecret不匹配" + clientDetails.getClientSecret());
        }else {
            Map<String, String> map=new HashMap<>();
            UserBean user = (UserBean) authentication.getPrincipal();
            map.put("username",user.getUsername());
            map.put("password",user.getPassword());
            //更新最后一次登录时间
            Map<String,Object> userMap=new HashMap<>();
            userMap.put("userUuid",user.getUserUuid());
            userMap.put("timeOnline", LocalDateTime.now());
            userMapper.updateOnlineTime(userMap);

            TokenRequest tokenRequest = new TokenRequest(map,CLIENT_ID,clientDetails.getScope(),GRANT_TYPE);

            OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);

            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request,authentication);
            OAuth2AccessToken accessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
//            System.out.println(accessToken.getValue());
            String token = authorizationServerTokenServices.refreshAccessToken(accessToken.getRefreshToken().getValue(), tokenRequest).getValue();
            System.out.println(token);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.write(objectMapper.writeValueAsString(new Response<>(ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getMsg(), accessToken.getValue())));
            writer.flush();
        }
    }
}
